const {
    AdView,
    User,
    PointsTransaction,
    sequelize
} = require('../models')
const logger = require('../utils/logger')
const redisClient = require('../config/redis')
const {
    Op
} = require('sequelize')

/**
 * 广告统计服务
 */
class AdStatisticsService {
    /**
     * 获取广告概览统计
     * @param {Object} filters - 过滤条件
     * @returns {Object} 统计数据
     */
    static async getOverviewStats(filters = {}) {
        try {
            const whereCondition = this.buildWhereCondition(filters)

            // 基础统计
            const [
                totalViews,
                completedViews,
                uniqueUsers,
                totalRewards,
                avgViewDuration
            ] = await Promise.all([
                AdView.count({
                    where: whereCondition
                }),
                AdView.count({
                    where: {
                        ...whereCondition,
                        is_completed: 1
                    }
                }),
                AdView.count({
                    where: whereCondition,
                    distinct: true,
                    col: 'user_id'
                }),
                AdView.sum('points_rewarded', {
                    where: whereCondition
                }),
                AdView.findOne({
                    where: whereCondition,
                    attributes: [
                        [sequelize.fn('AVG', sequelize.col('view_duration')), 'avgDuration']
                    ],
                    raw: true
                })
            ])

            // 计算衍生指标
            const completionRate = totalViews > 0 ? (completedViews / totalViews * 100) : 0
            const avgRewardPerView = completedViews > 0 ? (totalRewards / completedViews) : 0
            const avgViewsPerUser = uniqueUsers > 0 ? (totalViews / uniqueUsers) : 0

            return {
                totalViews,
                completedViews,
                uniqueUsers,
                totalRewards: parseFloat(totalRewards || 0),
                completionRate: parseFloat(completionRate.toFixed(2)),
                avgViewDuration: parseFloat(avgViewDuration?.avgDuration || 0),
                avgRewardPerView: parseFloat(avgRewardPerView.toFixed(2)),
                avgViewsPerUser: parseFloat(avgViewsPerUser.toFixed(2))
            }
        } catch (error) {
            logger.error('获取广告概览统计失败:', error)
            throw error
        }
    }

    /**
     * 获取时间趋势数据
     * @param {Object} filters - 过滤条件
     * @returns {Array} 趋势数据
     */
    static async getTrendData(filters = {}) {
        try {
            const {
                groupBy = 'day'
            } = filters
            const whereCondition = this.buildWhereCondition(filters)

            // 根据groupBy确定时间格式
            let dateFormat
            switch (groupBy) {
                case 'hour':
                    dateFormat = '%Y-%m-%d %H:00:00'
                    break
                case 'day':
                    dateFormat = '%Y-%m-%d'
                    break
                case 'week':
                    dateFormat = '%Y-%u'
                    break
                case 'month':
                    dateFormat = '%Y-%m'
                    break
                default:
                    dateFormat = '%Y-%m-%d'
            }

            const trendData = await AdView.findAll({
                attributes: [
                    [sequelize.fn('DATE_FORMAT', sequelize.col('created_at'), dateFormat), 'period'],
                    [sequelize.fn('COUNT', sequelize.col('id')), 'views'],
                    [sequelize.fn('SUM', sequelize.col('is_completed')), 'completedViews'],
                    [sequelize.fn('COUNT', sequelize.fn('DISTINCT', sequelize.col('user_id'))), 'uniqueUsers'],
                    [sequelize.fn('SUM', sequelize.col('points_rewarded')), 'totalRewards'],
                    [sequelize.fn('AVG', sequelize.col('view_duration')), 'avgDuration']
                ],
                where: whereCondition,
                group: [sequelize.fn('DATE_FORMAT', sequelize.col('created_at'), dateFormat)],
                order: [
                    [sequelize.fn('DATE_FORMAT', sequelize.col('created_at'), dateFormat), 'ASC']
                ],
                raw: true
            })

            return trendData.map(item => ({
                period: item.period,
                views: parseInt(item.views),
                completedViews: parseInt(item.completedViews),
                uniqueUsers: parseInt(item.uniqueUsers),
                totalRewards: parseFloat(item.totalRewards || 0),
                completionRate: item.views > 0 ? (item.completedViews / item.views * 100).toFixed(2) : 0,
                avgDuration: parseFloat(item.avgDuration || 0)
            }))
        } catch (error) {
            logger.error('获取时间趋势数据失败:', error)
            throw error
        }
    }

    /**
     * 获取平台分布统计
     * @param {Object} filters - 过滤条件
     * @returns {Array} 平台统计数据
     */
    static async getPlatformStats(filters = {}) {
        try {
            const whereCondition = this.buildWhereCondition(filters)

            const platformStats = await AdView.findAll({
                attributes: [
                    'platform',
                    [sequelize.fn('COUNT', sequelize.col('id')), 'views'],
                    [sequelize.fn('SUM', sequelize.col('is_completed')), 'completedViews'],
                    [sequelize.fn('COUNT', sequelize.fn('DISTINCT', sequelize.col('user_id'))), 'uniqueUsers'],
                    [sequelize.fn('SUM', sequelize.col('points_rewarded')), 'totalRewards'],
                    [sequelize.fn('AVG', sequelize.col('view_duration')), 'avgDuration']
                ],
                where: whereCondition,
                group: ['platform'],
                order: [
                    [sequelize.fn('COUNT', sequelize.col('id')), 'DESC']
                ],
                raw: true
            })

            return platformStats.map(item => ({
                platform: item.platform,
                views: parseInt(item.views),
                completedViews: parseInt(item.completedViews),
                uniqueUsers: parseInt(item.uniqueUsers),
                totalRewards: parseFloat(item.totalRewards || 0),
                completionRate: item.views > 0 ? (item.completedViews / item.views * 100).toFixed(2) : 0,
                avgDuration: parseFloat(item.avgDuration || 0)
            }))
        } catch (error) {
            logger.error('获取平台分布统计失败:', error)
            throw error
        }
    }

    /**
     * 获取广告类型统计
     * @param {Object} filters - 过滤条件
     * @returns {Array} 广告类型统计数据
     */
    static async getAdTypeStats(filters = {}) {
        try {
            const whereCondition = this.buildWhereCondition(filters)

            const adTypeStats = await AdView.findAll({
                attributes: [
                    'ad_type',
                    [sequelize.fn('COUNT', sequelize.col('id')), 'views'],
                    [sequelize.fn('SUM', sequelize.col('is_completed')), 'completedViews'],
                    [sequelize.fn('COUNT', sequelize.fn('DISTINCT', sequelize.col('user_id'))), 'uniqueUsers'],
                    [sequelize.fn('SUM', sequelize.col('points_rewarded')), 'totalRewards'],
                    [sequelize.fn('AVG', sequelize.col('view_duration')), 'avgDuration']
                ],
                where: whereCondition,
                group: ['ad_type'],
                order: [
                    [sequelize.fn('COUNT', sequelize.col('id')), 'DESC']
                ],
                raw: true
            })

            return adTypeStats.map(item => ({
                adType: item.ad_type,
                views: parseInt(item.views),
                completedViews: parseInt(item.completedViews),
                uniqueUsers: parseInt(item.uniqueUsers),
                totalRewards: parseFloat(item.totalRewards || 0),
                completionRate: item.views > 0 ? (item.completedViews / item.views * 100).toFixed(2) : 0,
                avgDuration: parseFloat(item.avgDuration || 0)
            }))
        } catch (error) {
            logger.error('获取广告类型统计失败:', error)
            throw error
        }
    }

    /**
     * 获取收益分析
     * @param {Object} filters - 过滤条件
     * @returns {Object} 收益分析数据
     */
    static async getRevenueAnalysis(filters = {}) {
        try {
            const whereCondition = this.buildWhereCondition(filters)

            // 基础收益数据
            const revenueData = await AdView.findAll({
                attributes: [
                    [sequelize.fn('SUM', sequelize.col('points_rewarded')), 'totalRewards'],
                    [sequelize.fn('COUNT', sequelize.col('id')), 'totalViews'],
                    [sequelize.fn('SUM', sequelize.col('is_completed')), 'completedViews']
                ],
                where: whereCondition,
                raw: true
            })

            const totalRewards = parseFloat(revenueData[0]?.totalRewards || 0)
            const totalViews = parseInt(revenueData[0]?.totalViews || 0)
            const completedViews = parseInt(revenueData[0]?.completedViews || 0)

            // 按广告类型的收益分析
            const revenueByAdType = await AdView.findAll({
                attributes: [
                    'ad_type',
                    [sequelize.fn('SUM', sequelize.col('points_rewarded')), 'rewards'],
                    [sequelize.fn('COUNT', sequelize.col('id')), 'views'],
                    [sequelize.fn('SUM', sequelize.col('is_completed')), 'completedViews']
                ],
                where: whereCondition,
                group: ['ad_type'],
                order: [
                    [sequelize.fn('SUM', sequelize.col('points_rewarded')), 'DESC']
                ],
                raw: true
            })

            // 计算预估广告收入（假设每个积分对应0.01元收入）
            const pointToRevenueRatio = 0.01
            const estimatedRevenue = totalRewards * pointToRevenueRatio

            return {
                totalRewards,
                totalViews,
                completedViews,
                estimatedRevenue: parseFloat(estimatedRevenue.toFixed(2)),
                avgRewardPerView: completedViews > 0 ? (totalRewards / completedViews).toFixed(3) : 0,
                revenueByAdType: revenueByAdType.map(item => ({
                    adType: item.ad_type,
                    rewards: parseFloat(item.rewards || 0),
                    views: parseInt(item.views),
                    completedViews: parseInt(item.completedViews),
                    estimatedRevenue: parseFloat((item.rewards * pointToRevenueRatio).toFixed(2))
                }))
            }
        } catch (error) {
            logger.error('获取收益分析失败:', error)
            throw error
        }
    }

    /**
     * 获取实时统计数据
     * @returns {Object} 实时统计数据
     */
    static async getRealTimeStats() {
        try {
            const cacheKey = 'ad_stats:realtime'

            // 尝试从缓存获取
            const cachedData = await redisClient.get(cacheKey)
            if (cachedData) {
                return JSON.parse(cachedData)
            }

            const now = new Date()
            const oneHourAgo = new Date(now.getTime() - 60 * 60 * 1000)
            const oneDayAgo = new Date(now.getTime() - 24 * 60 * 60 * 1000)

            const [
                lastHourViews,
                todayViews,
                onlineUsers
            ] = await Promise.all([
                AdView.count({
                    where: {
                        created_at: {
                            [Op.gte]: oneHourAgo
                        }
                    }
                }),
                AdView.count({
                    where: {
                        created_at: {
                            [Op.gte]: oneDayAgo
                        }
                    }
                }),
                AdView.count({
                    where: {
                        created_at: {
                            [Op.gte]: new Date(now.getTime() - 5 * 60 * 1000)
                        } // 5分钟内
                    },
                    distinct: true,
                    col: 'user_id'
                })
            ])

            const realTimeData = {
                lastHourViews,
                todayViews,
                onlineUsers,
                timestamp: now.toISOString()
            }

            // 缓存1分钟
            await redisClient.setex(cacheKey, 60, JSON.stringify(realTimeData))

            return realTimeData
        } catch (error) {
            logger.error('获取实时统计数据失败:', error)
            throw error
        }
    }

    /**
     * 生成统计报表
     * @param {Object} options - 报表选项
     * @returns {Object} 报表数据
     */
    static async generateReport(options = {}) {
        try {
            const {
                startDate,
                endDate,
                includeOverview = true,
                includeTrend = true,
                includePlatform = true,
                includeAdType = true,
                includeRevenue = true
            } = options

            const filters = {
                startDate,
                endDate
            }
            const report = {
                generatedAt: new Date().toISOString(),
                period: {
                    startDate,
                    endDate
                },
                data: {}
            }

            // 并行获取各种统计数据
            const promises = []

            if (includeOverview) {
                promises.push(
                    this.getOverviewStats(filters).then(data => ({
                        type: 'overview',
                        data
                    }))
                )
            }

            if (includeTrend) {
                promises.push(
                    this.getTrendData(filters).then(data => ({
                        type: 'trend',
                        data
                    }))
                )
            }

            if (includePlatform) {
                promises.push(
                    this.getPlatformStats(filters).then(data => ({
                        type: 'platform',
                        data
                    }))
                )
            }

            if (includeAdType) {
                promises.push(
                    this.getAdTypeStats(filters).then(data => ({
                        type: 'adType',
                        data
                    }))
                )
            }

            if (includeRevenue) {
                promises.push(
                    this.getRevenueAnalysis(filters).then(data => ({
                        type: 'revenue',
                        data
                    }))
                )
            }

            const results = await Promise.all(promises)

            // 组织报表数据
            results.forEach(result => {
                report.data[result.type] = result.data
            })

            return report
        } catch (error) {
            logger.error('生成统计报表失败:', error)
            throw error
        }
    }

    /**
     * 构建查询条件
     * @param {Object} filters - 过滤条件
     * @returns {Object} Sequelize查询条件
     */
    static buildWhereCondition(filters) {
        const whereCondition = {}

        if (filters.startDate && filters.endDate) {
            whereCondition.created_at = {
                [Op.between]: [new Date(filters.startDate), new Date(filters.endDate)]
            }
        } else if (filters.startDate) {
            whereCondition.created_at = {
                [Op.gte]: new Date(filters.startDate)
            }
        } else if (filters.endDate) {
            whereCondition.created_at = {
                [Op.lte]: new Date(filters.endDate)
            }
        }

        if (filters.platform) {
            whereCondition.platform = filters.platform
        }

        if (filters.adType) {
            whereCondition.ad_type = filters.adType
        }

        if (filters.userId) {
            whereCondition.user_id = filters.userId
        }

        if (filters.isCompleted !== undefined) {
            whereCondition.is_completed = filters.isCompleted ? 1 : 0
        }

        return whereCondition
    }

    /**
     * 清理过期的统计缓存
     */
    static async clearExpiredCache() {
        try {
            const keys = await redisClient.keys('ad_stats:*')
            if (keys.length > 0) {
                await redisClient.del(keys)
            }
            logger.info('清理广告统计缓存完成')
        } catch (error) {
            logger.error('清理广告统计缓存失败:', error)
        }
    }
}

module.exports = AdStatisticsService